using CoreProject.Api;
using CoreProject.IService;
using CoreProject.Model;
using CoreProject.Service;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.Dynamic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Core8Project.Api.Controllers
{
  [Route("api/[controller]")]
  [ApiController]
  public class AuthenticationController : ControllerBase
  {
    private readonly IConfiguration _configuration;
    private readonly IUsersService _service;

    public AuthenticationController(IConfiguration configuration, IUsersService service)
    {
      this._configuration = configuration;
      this._service = service;
    }

    [HttpGet]
    public async Task<ResultData<AuthUser>> Login(string loginName, string loginPwd)
    {

      ResultData<AuthUser> result = new ResultData<AuthUser>();

      if (string.IsNullOrWhiteSpace(loginName) || string.IsNullOrWhiteSpace(loginPwd))
      {

        result.code = "-1";
        result.msg = "账户密码不能为空！";
        return result;
      }


      var user = await ValidateUser(loginName, loginPwd);

      if (user != null)
      {
        if (user.Status)
        {
          //验证通过
          //返回Token  （票）
          result.state = 200;
          result.code = "1";
          result.msg = "登录成功！";
          result.data = new AuthUser()
          {
              UserID=user.UserId,
              RoleID=user.UserId,
            UserName = user.UserName,
            ImgPath = user.Img.Path,
            Token = GetJwtToken(user.Role.RoleName, user.RoleId, user.UserId)
          };
          return result;
        }
        else {
          result.state = 200;
          result.code = "-3";
          result.msg = "账户被冻结！";
          return result;
        }
       
      }
      else
      {
        result.state = 200;
        result.code = "-2";
        result.msg = "账户或者密码错误！";
        return result;
      }
    }

    /// <summary>
    /// 颁发令牌接口
    /// </summary>
    /// <returns></returns>
    [HttpGet(nameof(GetJwtToken))]
    public string GetJwtToken(string userRole, int roleID, int userID)
    {
      //获取在配置文件中获取Jwt属性设置
      string key = _configuration["JwtSettings:SecurityKey"];
      //Appsettings.app(new string[] { "JwtSettings", "SecurityKey" });
      string issuer = _configuration["JwtSettings:Issuer"];
      //Appsettings.app(new string[] { "JwtSettings", "Issuer" });
      string audience = _configuration["JwtSettings:Audience"];
      //Appsettings.app(new string[] { "JwtSettings", "Audience" });
      string expireminutes = _configuration["JwtSettings:ExpireMinutes"];

      //创建授权的token类
      SecurityToken securityToken = new JwtSecurityToken(
          issuer: issuer, //签发人
          audience: audience, //受众
          signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)), SecurityAlgorithms.HmacSha256), //秘钥

          //创建过期时间
          expires: DateTime.Now.AddMinutes(double.Parse(expireminutes)), //过期时间 

          //自定义JWT字段
          claims: new Claim[] {
                    //把模拟请求的角色权限添加到Role中 
                    new Claim(ClaimTypes.Role,userRole),
                    new Claim("UserID",userID.ToString()),
                    new Claim("RoleID",roleID.ToString()),
            //下面的都是自定义字段，可以任意添加到Claim作为信息共享
            //new Claim("Name","我叫lilili"),
            //new Claim("Age","18"),
          }
      );
      //返回请求token
      //return JsonConvert.SerializeObject(new { token = new JwtSecurityTokenHandler().WriteToken(securityToken) });

      return new JwtSecurityTokenHandler().WriteToken(securityToken);
    }

    //校验用户名密码（正式环境中应该是数据库校验）
    private async Task<User> ValidateUser(string loginName, string loginPwd)
    {
      loginPwd = MD5Helper.Md5(loginPwd, "X2");
      return await _service.Login(loginName,loginPwd); ;
    }
  }


  public class AuthUser
  {
    public int UserID { get; set; }
    public string UserName { get; set; }
    public string ImgPath { get; set; }
    public string Token { get; set; }
    public int RoleID { get; set; }
  }
}
